package com.wanlian.dao.impl;

import com.wanlian.common.PageCondition;
import com.wanlian.common.TypeChange;
import com.wanlian.dao.DeviceDao;
import com.wanlian.entity.Device;
import com.wanlian.error.SuccessCode;
import com.wanlian.model.ResultModel;
import com.wanlian.util.DateUtil;
import com.wanlian.util.StringUtil;
import com.wanlian.vo.DeviceListVo;
import com.wanlian.vo.Page;
import org.hibernate.Session;
import org.hibernate.jdbc.Work;
import org.springframework.stereotype.Component;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.text.ParseException;
import java.util.*;

@Component
public class DeviceDaoImpl extends GenericDaoImpl<Device> implements DeviceDao {

    public DeviceDaoImpl() {
        super(Device.class);
    }

    @Override
    public ResultModel queryDevice(Page page, Map<String, Object> conditions) {
        StringBuilder sqlWhere = new StringBuilder(" where 1=1 ");
        ArrayList<Object> param = new ArrayList<Object>();
        if (conditions != null) {
            if (conditions.containsKey("macAddress")) {
                String macAddress = (String) conditions.get("macAddress");
                if (StringUtil.hasValue(macAddress)) {
                    sqlWhere.append(" and macAddress like ?");
                    param.add("%" + macAddress + "%");
                }
            }
            if (conditions.containsKey("userid")) {
                try {
                    int userid = (int) conditions.get("userid");
                    if (StringUtil.hasValue(userid + "")) {
                        sqlWhere.append(" and userid=?");
                        param.add(userid);
                    }
                } catch (Exception e) {
                    System.out.println("为非数字" + e.toString());
                }

            }
            if (conditions.containsKey("deviceId")) {
                String deviceId = (String) conditions.get("deviceId");
                if (StringUtil.hasValue(deviceId)) {
                    sqlWhere.append(" and deviceId like ?");
                    param.add("%" + deviceId + "%");
                }
            }
        }
        List<Device> lists = new ArrayList<Device>();
        String hql = String.format("from %s " + sqlWhere, entityClassName());
        lists = this.queryForListByPage(hql, param.toArray(), page);
        String countSql = String.format("select count(*) from %s" + sqlWhere, entityClassName());
        long count = this.queryCount(countSql, param.toArray());
        ResultModel resultModel = new ResultModel(true, lists, count);
        return resultModel;
    }

    @Override
    public List<Device> queryDeviceByUser(Page page, String userName) {
        return null;
    }


    @Override
    public ResultModel queryDeviceByUser(Page page, int userId) {
        List<Device> lists = new ArrayList<Device>();
        String hql = String.format("from %s where isEnable =true and userId=? order by iscurrent desc ", entityClassName());
        lists = this.queryForListByPage(hql, new Object[]{userId}, page);
        String countsql = String.format("select count(*) from %s where userId=?", entityClassName());
        long count = this.queryCount(countsql, new Object[]{userId});
        ResultModel resultModel = new ResultModel();
        resultModel.setObject(lists);
        resultModel.setCount(count);
        return resultModel;
    }

    @Override
    public List<Device> queryDevicesByUser(int userId) {
        List<Device> lists = new ArrayList<Device>();
        String hql = String.format("from %s where isEnable =true and userId=? order by iscurrent desc ", entityClassName());
        lists = this.queryForList(hql, new Object[]{userId});
        return lists;
    }


    @Override
    public ResultModel deleteById(int id) {
        ResultModel resultModel = new ResultModel();
        Device device = this.queryById(id);
        if (device != null) {
            device.setEnable(false);
            this.update(device);
            resultModel.setMessage(SuccessCode.SUCCESS_UPD);
            resultModel.setBresult(true);
        } else {
            resultModel.setBresult(false);
            resultModel.setMessage(SuccessCode.DEVICE_NOTFIND);
        }
        return resultModel;
    }

    @Override
    public ResultModel deleteByDeviceId(String deviceId) {
        ResultModel resultModel = new ResultModel();
        String hql = String.format("from %s where deviceId=?", entityClassName());
        Device device = this.queryForObject(hql, new Object[]{deviceId});
        if (device != null) {
            device.setEnable(false);
            this.update(device);
            resultModel.setBresult(true);
        } else {
            resultModel.setBresult(false);
            resultModel.setMessage(SuccessCode.DEVICE_NOTFIND);
        }
        return resultModel;
    }

    /**
     * 启动设备
     *
     * @param id
     * @return
     */
    @Override
    public ResultModel doEnableById(int id) {
        ResultModel resultModel = new ResultModel();
        Device device = this.queryById(id);
        if (device != null) {
            device.setEnable(true);
            this.update(device);
            resultModel.setMessage(SuccessCode.DEVICE_ENABLE);
            resultModel.setBresult(true);
        } else {
            resultModel.setBresult(false);
            resultModel.setMessage(SuccessCode.DEVICE_NOTFIND);
        }
        return resultModel;
    }

    /**
     * 启用设备
     *
     * @param deviceId
     * @return
     */
    @Override
    public ResultModel doEnableByDeviceId(String deviceId) {
        ResultModel resultModel = new ResultModel();
        Device device = this.queryByDeviceId(deviceId);
        if (device != null) {
            device.setEnable(true);
            this.update(device);
            resultModel.setBresult(true);
        } else {
            resultModel.setBresult(false);
            resultModel.setMessage(SuccessCode.DEVICE_NOTFIND);
        }
        return resultModel;
    }

    @Override
    public ResultModel bindDeviceById(int id, int userId) {
        ResultModel resultModel = new ResultModel();
        Device device = this.queryById(id);
        if (device != null) {
            device.setEnable(true);
            device.setUserid(userId);
            this.update(device);
            resultModel.setBresult(true);
        } else {
            resultModel.setBresult(false);
            resultModel.setMessage(SuccessCode.DEVICE_NOTFIND);
        }
        return resultModel;
    }

    @Override
    public ResultModel doBindDeviceByDeviceKey(String deviceKey, int userId) {
        ResultModel resultModel = new ResultModel();
        String hql = String.format("from %s where deviceKey=?", entityClassName());
        Device device = this.queryForObject(hql, new Object[]{deviceKey});
        if (device != null) {
            Device device1 = this.queryCurrentByUserId(userId);
            if (device1 != null) {
                device1.setCurrent(false);
                this.update(device1);
            }
            device.setEnable(true);
            device.setHasBind(true);
            device.setActive(true);
            device.setBindFirst(false);
            device.setActiveTime(DateUtil.currentTimestamp());
            device.setUserid(userId);
            device.setCurrent(true);
            this.update(device);
            resultModel.setMessage("绑定成功");
            resultModel.setBresult(true);
        } else {
            resultModel.setBresult(false);
            resultModel.setMessage(SuccessCode.DEVICE_NOTFIND);
        }
        return resultModel;
    }


    @Override
    public Device queryByDeviceId(String deviceId) {
        String hql = String.format("from %s where deviceId=?", entityClassName());
        Device device = this.queryForObject(hql, new Object[]{deviceId});
        return device;
    }


    @Override
    public Device queryByDeMac(String deviceId, String macAddress) {
        String hql = String.format("from %s where deviceId=? and macAddress=?", entityClassName());
        Device device = this.queryForObject(hql, new Object[]{deviceId, macAddress});
        return device;
    }

    @Override
    public Device queryByDeviceKey(String deviceKey) {
        String hql = String.format("from %s where devicekey=?", entityClassName());
        Device device = this.queryForObject(hql, new Object[]{deviceKey});
        return device;
    }

    @Override
    public Device queryByMac(String mac) {
        String hql = String.format("from %s where macAddress=?", entityClassName());
        Device device = this.queryForObject(hql, new Object[]{mac});
        return device;
    }


    @Override
    public ResultModel queryDeviceByParams(PageCondition pageCondition, int userId) {
        String[] column = {"version", "devicekey", "deviceid", "channel", "devicename", "macaddress", "username", "isactive", "isenable", "hasbind", "isonline", "uid", "did"};
        String sql = "select  d.version,d.devicekey,d.deviceid,(select tpname from tb_wordbook where wbval1=d.channel) as channel,d.devicename,d.macaddress,u.username,d.isactive,d.isenable,d.hasbind,d.isonline,u.id as uid,d.id as did from tb_device d left join  tb_user u on d.userid=u.id where 1=1 ";
        StringBuilder sqlWhere = new StringBuilder();
        ArrayList<Object> param = new ArrayList<Object>();
        if (userId != 0) {
            sqlWhere.append(" and u.id=? ");
            param.add(userId);
        }

        if (pageCondition.isEmpty("macAddress")) {
            String macAddress = (String) pageCondition.getByKey("macAddress");
            sqlWhere.append(" and d.macAddress  like ? ");
            param.add("%" + macAddress + "%");
        }
        if (pageCondition.isEmpty("deviceId")) {
            String deviceId = (String) pageCondition.getByKey("deviceId");
            sqlWhere.append(" and d.deviceId like ? ");
            param.add("%" + deviceId + "%");
        }
        if (pageCondition.isEmpty("hasBind")) {
            int hasBind = Integer.parseInt((String) pageCondition.getByKey("hasBind"));
            sqlWhere.append(" and d.hasBind=?");
            param.add(hasBind);
        }
        if (pageCondition.isEmpty("isactive")) {
            int isactive = Integer.parseInt((String) pageCondition.getByKey("isactive"));
            sqlWhere.append(" and d.isactive=?");
            param.add(isactive);
        }
        if (pageCondition.isEmpty("username")) {
            String username = (String) pageCondition.getByKey("username");
            sqlWhere.append(" and u.username=?");
            param.add(username);
        }
        if (pageCondition.isEmpty("devicename")) {
            String devicename = (String) pageCondition.getByKey("devicename");
            sqlWhere.append(" and d.devicename=?");
            param.add(devicename);
        }
        if (pageCondition.isExistByKey("userId")) {
            int userIds = TypeChange.stringToInt(pageCondition.getByKey("userId").toString());
            if (userIds > 0) {
                sqlWhere.append(" and u.id=?");
                param.add(userIds);
            }
        }
        List<Map<String, Object>> lists = this.queryForListObjectByPage(sql + sqlWhere + "", param.toArray(), pageCondition.getPage(), column);
        int count = this.queryCountByParam("select count(1) from tb_device d left join  tb_user u on d.userid=u.id where 1=1 " + sqlWhere, param.toArray());
        ResultModel resultModel = new ResultModel(true, lists, count);
        return resultModel;
    }

    @Override
    public long queryUserDeviceCount(int userId) {
        String countsql = String.format("select count(*) from %s where userId=?", entityClassName());
        long count = this.queryCount(countsql, new Object[]{userId});
        return count;
    }

    @Override
    public Device queryDeviceByUserId(int userId) {
        String hql = String.format("from %s where iscurrent=? and userid=?", entityClassName());
        Device device = this.queryForObject(hql, new Object[]{true, userId});
        return device;
    }

    @Override
    public void doSetDeviceCurrent(String deviceId, int userid) {
        List<Device> devices = this.queryAllByUserId(userid);
        for (Device device : devices) {
            if (device.getDeviceId().equals(deviceId)) {
                device.setCurrent(true);
                this.update(device);
            } else {
                device.setCurrent(false);
                this.update(device);
            }
        }
    }

    @Override
    public List<Device> queryAllByUserId(int userId) {
        String hql = String.format("from %s where userid=?", entityClassName());
        List<Device> devices = this.queryForList(hql, new Object[]{userId});
        return devices;
    }

    @Override
    public List<Device> queryDevicesByChannels(List<String> channels) {
        String inParam = "";
        for (String item : channels) {
            inParam += String.format("'%s',", item);
        }
        inParam = inParam.substring(0, inParam.length() - 1);
        inParam = String.format("(%s)", inParam);

        String hql = String.format("from %s where channel in %s ", entityClassName(), inParam);
        List<Device> devices = this.queryForList(hql, new Object[]{});
        return devices;
    }

    @Override
    public List<Device> queryEnableDevicesByChannels(List<String> channels) {
        String inParam = "";
        for (String item : channels) {
            inParam += String.format("'%s',", item);
        }
        inParam = inParam.substring(0, inParam.length() - 1);
        inParam = String.format("(%s)", inParam);

        String hql = String.format("from %s where channel in %s and isenable=? and hasbind=?", entityClassName(), inParam);
        List<Device> devices = this.queryForList(hql, new Object[]{true, true});
        return devices;
    }

    @Override
    public List<Device> queryDeviceOnline() {
        String hql = String.format("from %s where  isenable =? and isonline =? ", entityClassName());
        List<Device> devices = this.queryForList(hql, new Object[]{true, true});
        return devices;
    }

    @Override
    public Device doEditUntied(Device device, int userId) {

        return null;
    }


    @Override
    public Device queryDeviceByUdid(String deviceId, int userId) {
        String hql = String.format("from %s where deviceId=? and userid=?", entityClassName());
        Device device = this.queryForObject(hql, new Object[]{deviceId, userId});
        return device;
    }


    @Override
    public Device queryCurrentByUserId(int userId) {
        String hql = String.format("from %s where iscurrent=1 and userid=?", entityClassName());
        Device device = this.queryForObject(hql, new Object[]{userId});
        return device;
    }


    @Override
    public long queryDeviceCountToday() {
        try {
            Date dateNow = DateUtil.currentDate();
            String today = DateUtil.formatDateNoHour(dateNow);
            String countsql = String.format("select count(*) from %s where activetime> date(?) ", entityClassName());
            long count = this.queryCount(countsql, new Object[]{today});
            return count;
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return 0;
    }

    @Override
    public Device queryByDeviceKeyNot(int id, String deviceKey) {
        String hql = String.format("from %s where devicekey=? and id!=?", entityClassName());
        Device device = this.queryForObject(hql, new Object[]{deviceKey, id});
        return device;
    }

    @Override
    public List<String> queryAllDeviceList() {
        String hql = String.format("select devicekey,'' from tb_device where isenable=? and isonline=? ");
        List<Object[]> objects = this.queryForListCu(hql, new Object[]{true,true});
        List<String> devices = new ArrayList<>();
        for (Object[] obj : objects) {
            if (!devices.contains(obj[0].toString())) {
                devices.add(obj[0].toString());
            }
        }
        return devices;
    }

    @Override
    public Map<String, Device> queryAllDevices() {
        String hql = String.format("from %s where isenable=? and isonline=? ", entityClassName());
        List<Device> devices = this.queryForList(hql, new Object[]{true,true});
        Map<String, Device> deviceMap = new HashMap<>();
        for (Device item : devices) {
            if (!deviceMap.containsKey(item.getDevicekey())) {
                deviceMap.put(item.getDevicekey(), item);
            }
        }
        return deviceMap;
    }

    @Override
    public Device queryByMacNot(int id, String mac) {
        String hql = String.format("from %s where macAddress=? and id !=?", entityClassName());
        Device device = this.queryForObject(hql, new Object[]{mac, id});
        return device;
    }

    @Override
    public List<Device> queryDeviceOnlineAll() {
        String hql = String.format("from %s where   isenable=? and isonline=? ", entityClassName());
        List<Device> devices = this.queryForList(hql, new Object[]{true, true});
        return devices;
    }

    @Override
    public void EditBatch(List<Device> devices) {
        if (devices.size() > 0) {
            String sqlwhere = "";
            for (Device devce : devices) {
                sqlwhere = sqlwhere + devce.getId() + ",";
            }
            sqlwhere = sqlwhere.substring(0, sqlwhere.length() - 1);
            System.out.println("start~~" + DateUtil.currentTimestamp());
            this.updateByJdbc("update tb_device set isonline=false where id in (" + sqlwhere + ")", null);
            System.out.println("end~~" + DateUtil.currentTimestamp());
        }
    }

    @Override
    public void EditBatchLine(List<Device> devices) {
        if (devices.size() > 0) {
            String sqlOnline = "";
            String sqlOffline = "";
            for (Device device : devices) {
                boolean online = device.isOnline();
                if (online) {
                    sqlOnline = sqlOnline + "'" + device.getDevicekey() + "',";
                } else {
                    sqlOffline = sqlOffline + "'" + device.getDevicekey() + "',";
                }
            }
            if (sqlOnline.length() > 0) {
                sqlOnline = sqlOnline.substring(0, sqlOnline.length() - 1);
                this.updateByJdbc("update tb_device set isonline=1,version='1.0.1' where devicekey in (" + sqlOnline + ")", null);
            } else {
                sqlOffline = sqlOffline.substring(0, sqlOffline.length() - 1);
                this.updateByJdbc("update tb_device set isonline=0,version='1.0.1' where devicekey in (" + sqlOffline + ")", null);
            }
        }
    }
}
